package main.java.com.suncuicui.bi.FactoryMode.vo;

/**
 * Created by suncuicui on 2018/11/23.
 */
public class Singleton {
    private static Singleton instance = null;

    /**构造私有方法，防止实*/
    public Singleton() {
    }

    /**1.静态工厂方法，
     * 懒汉式，线程不安全
     * 创建实例,这个类可以满足基本要求了，但是放入多线程下，就会有问题了,解决办法2*/
   /* public static Singleton getInstance() {
        if(instance==null){
            instance = new Singleton();
        }
        return instance;
    }*/
    /**2 懒汉式，线程安全.
     * 对getInstance方法加synchronized关键字,synchronized关键字锁住的是这个对象
    这样的用法，在性能上会有所下降，
    因为每次调用getInstance()，都要对对象上锁，
    事实上，只有在第一次创建对象的时候需要加锁，
    之后就不需要了，所以，这个地方需要改进。我们改成3*/
   /* public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }*/
    /**3.第一次调用getInstance，会对对象上锁，将synchronized关键字加在了内部，
     * 也就是说当调用的时候是不需要加锁的，
     * 只有在instance为null，并创建对象的时候才需要加锁，性能有一定的提升，但是还是有问题，
     * 在Java指令中创建对象和赋值操作是分开进行的，也就是说instance = new Singleton();语句是分两步执行的。
     * 但是JVM并不保证这两个操作的先后顺序，也就是说有可能JVM会为新的Singleton实例分配空间，然后直接赋值给instance成员，然后再去初始化这个Singleton实例。
     * 这样就可能出错了，我们以A、B两个线程为例：
     * a)A和B同时进入了第一个if判断
     * b)A先进入synchronized块，由于instance为null,所以执行了instance = new Singleton();
     * c)由于jvm对instance = new Singleton();语句是分两步执行的，先分配了新的对象的工作空间，然后赋值给instance;此时还没有初始化，A就离开了
     * d）这时，B进入了synchronized块，此时instance!=null,所以B马上离开了
     * e)B准备使用instance，却发现instance没有初始化，于是，错误便发生了
     * 优化看SingletonAfterOptimization.java
     * */
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (instance) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    /**

     *
     * */

    /*
      */
    public Object readResolve() {
        return instance;
    }
}
